﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Ports;
using System.Text;
using System.Windows.Forms;
using thinger.DataConvertLib;

namespace SerialPortDemo_05
{
    public class MySerialPort
    {
        private SerialPort serialPort = new SerialPort();

        // 接收数据缓存
        private MemoryStream memoryBuffer = new MemoryStream();

        // 串口打开标识
        public bool open = false;

        // 接收事件
        public event Action<byte[]> receiveEvent;

        // 输出日志事件
        public event Action<string> showLogEvent;

        public int action = -1; // 0 读； 1写；

        public void initBy(ComboBox comboxPortName, ComboBox comboBoxBaudRate)
        {
            string[] port = System.IO.Ports.SerialPort.GetPortNames();

            comboxPortName.Items.AddRange(port);
            // 如果有数据显示第0个
            comboxPortName.SelectedIndex = comboxPortName.Items.Count > 0 ? 0 : -1;

            comboBoxBaudRate.Items.Add(1200);
            comboBoxBaudRate.Items.Add(4800);
            comboBoxBaudRate.Items.Add(9600);
            comboBoxBaudRate.Items.Add(14400);
            comboBoxBaudRate.Items.Add(19200);
            comboBoxBaudRate.Items.Add(38400);

            comboBoxBaudRate.SelectedItem = 9600;

        }

        public void openBy(string portName, int baudRate)
        {
            try
            {
                serialPort.DataReceived += new SerialDataReceivedEventHandler(SerialPortDataReceived);
                serialPort.PortName = portName;
                serialPort.BaudRate = baudRate;
                serialPort.DataBits = 8;
                serialPort.StopBits = StopBits.One;
                serialPort.Parity = Parity.None;
                serialPort.Open();

                open = true;
            }
            catch (Exception)
            {
                throw;
            }
        }

        public void close()
        {
            try
            {
                serialPort.Close();

                open = false;
            }
            catch (Exception)
            {
                throw;
            }
        }

        private void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                serialPort = (SerialPort)sender;
                byte[] bytebuffer = new byte[serialPort.BytesToRead];
                serialPort.Read(bytebuffer, 0, bytebuffer.Length);
                // 将接收到的数据写入缓存
                memoryBuffer.Write(bytebuffer);

                Debug.WriteLine("-------");
                Debug.WriteLine("mem length:" + memoryBuffer.Length);

                // 判断缓存长度 至少包括数据长度
                if (memoryBuffer.Length <= 2)
                {
                    return;
                }

                // 整包数据长度
                byte length = 0;

                switch(action)
                {
                    case 0:
                        length = (byte)(ByteLib.GetByteFromByteArray(memoryBuffer.ToArray(), 2) + 5); // 读响应长度
                        break;
                    case 1:
                        length = (byte)8; // 写响应长度
                        break;
                }

                Debug.WriteLine("length:" + length);

                // 判断缓存长度 
                if (memoryBuffer.Length < length)
                {
                    return;
                }

                byte[] temp = new byte[length - 2];
                byte[] tempCRC = new byte[2];

                Array.Copy(memoryBuffer.ToArray(), temp, temp.Length);
                Array.Copy(memoryBuffer.ToArray(), temp.Length, tempCRC, 0, 2);

                byte[] needCheckTemp = CRC.crc16(temp);

                Debug.WriteLine(StringLib.GetHexStringFromByteArray(temp) + " / " + StringLib.GetHexStringFromByteArray(tempCRC) + " ");
                Debug.WriteLine(StringLib.GetHexStringFromByteArray(needCheckTemp));
                Debug.WriteLine(!(tempCRC[0] == needCheckTemp[length - 2] && tempCRC[1] == needCheckTemp[length - 1]));
                Debug.WriteLine(tempCRC[0] + " " + needCheckTemp[length - 2] + " " + tempCRC[1] + " " + needCheckTemp[length - 1]);

                // 数据长度满足条件，判断校验位
                if (!(tempCRC[0] == needCheckTemp[length - 2] && tempCRC[1] == needCheckTemp[length - 1]))
                {
                    // 缓存清空
                    memoryBuffer = new MemoryStream();
                    action = -1;
                    return;
                }

                Debug.WriteLine("收到响应：" + StringLib.GetHexStringFromByteArray(memoryBuffer.ToArray()));
                showLogEvent?.Invoke("收到响应：" + StringLib.GetHexStringFromByteArray(memoryBuffer.ToArray()));

                receiveEvent?.Invoke(memoryBuffer.ToArray());

                // 缓存清空
                memoryBuffer = new MemoryStream();
                action = -1;
            }
            catch (Exception)
            {
                throw;
            }
        }

        public void sendReadRequest(byte[] buffer)
        {
            try
            {
                action = 0;
                write(buffer);

            }
            catch (Exception)
            {
                throw;
            }
        
        }
        public void sendWriteRequest(byte[] buffer)
        {
            try
            {
                action = 1;
                write(buffer);

            }
            catch (Exception)
            {
                throw;
            }
        }

        private void write(byte[] buffer)
        {
            try
            {
                byte[] request = CRC.crc16(buffer);

                memoryBuffer = new MemoryStream();

                Debug.WriteLine("发送请求：" + StringLib.GetHexStringFromByteArray(request));
                showLogEvent?.Invoke("发送请求：" + StringLib.GetHexStringFromByteArray(request));

                serialPort.Write(request, 0, request.Length);

            }
            catch (Exception)
            {
                throw;
            }
        }

    }
}
